# _*_ coding: utf-8 _*_
# .@FileName:lipSealMouth
# .@Data....:2025-05-10 : 15 : 57
# .@Aurhor..:LiuJingYu
"""
launch:
from __future__ import unicode_literals, print_function
import maya.cmds as mc
"""
# _*_ coding: utf-8 _*_
# .@FileName:lipSealMouth
# .@Data....:2025-05-10 : 15 : 57
# .@Aurhor..:LiuJingYu
"""
launch:
from __future__ import unicode_literals, print_function
import maya.cmds as mc
"""
import maya.cmds as cmds


def generate_node_name(base_name, node_type):
    """
    按指定前缀生成节点名称（核心命名规则）
    :param base_name: 基准对象名称（如控制Locator: "loc_m_mouthZipper_001"）
    :param node_type: 节点类型（决定前缀）
    :return: 格式化后的节点名称（示例: "blend_m_mouthZipper_001"）
    """
    # 定义节点类型到前缀的映射（严格按用户要求）
    prefix_map = {
        'blendColors': 'blend_',
        'multiplyDivide': 'md_',
        'reverse': 'rev_',
        'setRange': 'sr_',
        'plusMinusAverage': 'plus_',
        'clamp': 'clamp_'
    }

    # 验证节点类型有效性
    if node_type not in prefix_map:
        cmds.error(f"不支持的节点类型: {node_type}，请检查prefix_map配置")

    # 提取基准名称的核心部分（去掉首段"loc_"）
    name_parts = base_name.split('_')[1:]  # "loc_m_mouthZipper_001" → ["m", "mouthZipper", "001"]
    core_name = '_'.join(name_parts)  # → "m_mouthZipper_001"

    # 拼接前缀和核心名称
    return f"{prefix_map[node_type]}{core_name}"


def connect_blend_colors(color1_obj, color2_obj, output_obj, base_name):
    """
    创建blendColors节点并连接属性（使用指定前缀命名）
    """
    # 生成符合规则的blend节点名称（类型指定为blendColors）
    blend_node = cmds.createNode(
        'blendColors',
        name=generate_node_name(base_name, 'blendColors')
    )

    # 保持原有连接逻辑不变
    for src, dst in [
        (f"{color1_obj}.translate", f"{blend_node}.color1"),
        (f"{color2_obj}.translate", f"{blend_node}.color2"),
        (f"{blend_node}.output", f"{output_obj}.translate")
    ]:
        if not cmds.objExists(src):
            cmds.error(f"源属性不存在: {src}")
        if not cmds.objExists(dst):
            cmds.error(f"目标属性不存在: {dst}")
        cmds.connectAttr(src, dst, force=True)

    return blend_node


def setup_blender_connections(blend_nodes, locator_name):
    """
    封装blender属性连接逻辑（使用指定前缀命名）
    """
    # 健壮性检查（保持原有逻辑）
    if len(blend_nodes) != 2:
        cmds.error("blend_nodes参数需要包含2个blendColors节点")
    if not cmds.objExists(locator_name):
        cmds.error(f"未找到控制Locator: {locator_name}")
    for attr in ['seal', 'bias']:
        if not cmds.objExists(f"{locator_name}.{attr}"):
            cmds.error(f"Locator缺少必要属性: {locator_name}.{attr}")

    # 处理lower目标的multiplyDivide节点（类型指定为multiplyDivide）
    lower_md = cmds.createNode(
        'multiplyDivide',
        name=generate_node_name(locator_name, 'multiplyDivide')
    )
    cmds.connectAttr(f"{locator_name}.seal", f"{lower_md}.input1X", force=True)
    cmds.connectAttr(f"{locator_name}.bias", f"{lower_md}.input2X", force=True)
    cmds.connectAttr(f"{lower_md}.outputX", f"{blend_nodes[0]}.blender", force=True)

    # 处理upper目标的multiplyDivide和reverse节点（类型分别指定）
    upper_md = cmds.createNode(
        'multiplyDivide',
        name=generate_node_name(locator_name, 'multiplyDivide')
    )
    bias_reverse = cmds.createNode(
        'reverse',
        name=generate_node_name(locator_name, 'reverse')
    )

    cmds.connectAttr(f"{locator_name}.seal", f"{upper_md}.input1X", force=True)
    cmds.connectAttr(f"{locator_name}.bias", f"{bias_reverse}.inputX", force=True)
    cmds.connectAttr(f"{bias_reverse}.outputX", f"{upper_md}.input2X", force=True)
    cmds.connectAttr(f"{upper_md}.outputX", f"{blend_nodes[1]}.blender", force=True)

    return {
        "lower_md": lower_md,
        "upper_md": upper_md,
        "bias_reverse": bias_reverse
    }


def setup_range_clamp_connections(md_nodes, locator_name):
    """
    为multiplyDivide节点添加控制链（使用指定前缀命名）
    """
    # 健壮性检查（保持原有逻辑）
    if not cmds.objExists(locator_name):
        cmds.error(f"控制Locator不存在: {locator_name}")
    required_attrs = ['bias', 'lipSealLeft']
    for attr in required_attrs:
        if not cmds.objExists(f"{locator_name}.{attr}"):
            cmds.error(f"Locator缺少必要属性: {locator_name}.{attr}")
    if len(md_nodes) != 2:
        cmds.error("md_nodes参数需要包含2个multiplyDivide节点（lower_md, upper_md）")

    control_nodes = {}

    for md_node in md_nodes:
        # 基础检查（保持原有逻辑）
        if not cmds.objExists(md_node) or cmds.nodeType(md_node) != 'multiplyDivide':
            cmds.error(f"无效的multiplyDivide节点: {md_node}")

        output_dest = cmds.listConnections(f"{md_node}.outputX", plugs=True, destination=True)
        if not output_dest:
            cmds.warning(f"节点{md_node}无输出连接，跳过处理")
            continue

        # 创建控制节点组（使用各自的节点类型指定前缀）
        set_range_node = cmds.createNode(
            'setRange',
            name=generate_node_name(locator_name, 'setRange')
        )
        pma_node = cmds.createNode(
            'plusMinusAverage',
            name=generate_node_name(locator_name, 'plusMinusAverage')
        )
        clamp_node = cmds.createNode(
            'clamp',
            name=generate_node_name(locator_name, 'clamp')
        )

        # 配置setRange节点（保持原有逻辑）
        cmds.setAttr(f"{set_range_node}.maxX", 1)
        cmds.connectAttr(f"{locator_name}.lipSealLeft", f"{set_range_node}.valueX", force=True)

        # 连接setRange的maxX（保持原有逻辑）
        if md_node == md_nodes[0]:
            cmds.connectAttr(f"{locator_name}.bias", f"{set_range_node}.maxX", force=True)
            rev_node = None
        else:
            rev_connections = cmds.listConnections(f"{md_node}.input2X", source=True)
            rev_node = rev_connections[0] if rev_connections else None
            if not rev_node:
                cmds.error(f"无法获取{md_node}的反向节点，请检查连接")
            cmds.connectAttr(f"{rev_node}.outputX", f"{set_range_node}.maxX", force=True)

        # 连接plusMinusAverage节点（保持原有逻辑）
        cmds.connectAttr(f"{set_range_node}.outValueX", f"{pma_node}.input1D[0]", force=True)
        cmds.connectAttr(f"{md_node}.outputX", f"{pma_node}.input1D[1]", force=True)

        # 配置clamp节点（保持原有逻辑）
        cmds.connectAttr(f"{pma_node}.output1D", f"{clamp_node}.inputR", force=True)
        if md_node == md_nodes[0]:
            cmds.connectAttr(f"{locator_name}.bias", f"{clamp_node}.maxR", force=True)
        else:
            cmds.connectAttr(f"{rev_node}.outputX", f"{clamp_node}.maxR", force=True)

        # 断开原始连接并重新连接（保持原有逻辑）
        cmds.disconnectAttr(f"{md_node}.outputX", output_dest[0])
        cmds.connectAttr(f"{clamp_node}.outputR", output_dest[0], force=True)

        # 存储关键节点
        control_nodes[md_node] = {
            "setRange": set_range_node,
            "pma": pma_node,
            "clamp": clamp_node,
            "reverse": rev_node
        }

    return control_nodes

def setup_additional_set_range_chain(set_range_nodes, control_locator="loc_m_mouthZipper_001"):
    """
    封装原有setRange扩展连接逻辑（完全保留原始代码结构）
    :param set_range_nodes: setRange节点列表（顺序：[第一个setRange, 第二个setRange]）
    :param control_locator: 控制Locator名称（默认使用硬编码名称）
    """
    objs = set_range_nodes  # 直接使用传入的节点列表
    for i, j in enumerate(objs):

        range_node = cmds.createNode('setRange') # 避免与内置函数range冲突，建议改名但按原代码保留
        if i == 0:
            cmds.connectAttr(f'{control_locator}.bias', f'{range_node}.maxX')
        else:
            getRange = cmds.listConnections(f'{j}.maxX')[0]
            cmds.connectAttr(f'{getRange}.outputX', f'{range_node}.maxX')

        getPlus = cmds.listConnections(f'{j}.outValueX', p=True)[0]
        cmds.connectAttr(f'{control_locator}.lipSealRight', f'{range_node}.valueX')

        pmd = cmds.createNode('plusMinusAverage')
        cmds.connectAttr(f'{range_node}.outValueX', f'{pmd}.input1D[0]')
        cmds.connectAttr(f'{j}.outValueX', f'{pmd}.input1D[1]')

        clamp = cmds.createNode('clamp')
        cmds.connectAttr(f'{pmd}.output1D', f'{clamp}.inputR')
        cmds.setAttr(f'{clamp}.maxR', 1)
        cmds.connectAttr(f'{clamp}.outputR', getPlus, f=True)

# ---- 主执行流程 ----
# 获取选中对象并进行健壮性检查（保持原有逻辑）
selected_objs = cmds.ls(sl=True)
if not selected_objs:
    cmds.error("请先选择至少4个对象！")
if len(selected_objs) != 4:
    cmds.error(f"需要选择4个对象，当前选择了{len(selected_objs)}个")

# 解包对象（顺序：upperloc, lowerloc, lowerTarget, upperTarget）
upperloc, lowerloc, lowerTarget, upperTarget = selected_objs

# 定义控制Locator名称（作为命名基准）
control_locator = "loc_m_mouthZipper_001"  # 示例基准名称

# 创建blendColors节点（使用控制Locator作为命名基准）
blend_lower = connect_blend_colors(upperloc, lowerloc, lowerTarget, control_locator)
blend_upper = connect_blend_colors(lowerloc, upperloc, upperTarget, control_locator)

# 连接blender控制（自动生成符合规则的节点名）
connection_nodes = setup_blender_connections(
    blend_nodes=[blend_lower, blend_upper],
    locator_name=control_locator
)

md_nodes_to_process = [connection_nodes['lower_md'], connection_nodes['upper_md']]

# 设置范围限制连接（自动生成符合规则的节点名）
created_nodes = setup_range_clamp_connections(
    md_nodes=md_nodes_to_process,
    locator_name=control_locator
)


sr_nodes_to_process = [
    created_nodes[md_nodes_to_process[0]]['setRange'],
    created_nodes[md_nodes_to_process[1]]['setRange']
]
setup_additional_set_range_chain(sr_nodes_to_process,control_locator)



# 输出验证（示例输出）
print(
    f"创建的blend节点: {blend_lower}, {blend_upper}")  # 输出: blend_m_mouthZipper_001, blend_m_mouthZipper_001（注：实际会自动添加唯一后缀）
print(
    f"创建的md节点: {connection_nodes['lower_md']}, {connection_nodes['upper_md']}")  # 输出: md_m_mouthZipper_001, md_m_mouthZipper_001
print(f"创建的rev节点: {connection_nodes['bias_reverse']}")  # 输出: rev_m_mouthZipper_001
print(f"创建的sr节点: {created_nodes[md_nodes_to_process[0]]['setRange']}")  # 输出: sr_m_mouthZipper_001
print(f"创建的plus节点: {created_nodes[md_nodes_to_process[0]]['pma']}")  # 输出: plus_m_mouthZipper_001
print(f"创建的clamp节点: {created_nodes[md_nodes_to_process[0]]['clamp']}")  # 输出: clamp_m_mouthZipper_001

